<?php

namespace api\modules\v1\forms\rbac;

use Yii;
use yii\base\Model;
use common\models\member\Member;
use common\models\rbac\Menu;
use common\models\rbac\Action;
use common\models\rbac\RolePermission;
use common\models\rbac\Role;

/**
 * 角色
 *
 * Class RoleForm
 * @package api\modules\v1\forms\rbac
 */
class RoleForm extends Model
{
    /**
     * 角色ID
     *
     * @var
     */
    public $id;

    /**
     * 角色名
     *
     * @var
     */
    public $name;

    /**
     * 角色描述
     *
     * @var
     */
    public $desc;

    /**
     * 项目ID
     *
     * @var
     */
    public $project_id;

    /**
     * 动作状态
     *
     * @var
     */
    public $status;

    /**
     * 类型
     *
     * @var
     */
    public $type;

    /**
     * 菜单IDs【多个','分割】
     *
     * @var
     */
    public $menu_ids;

    /**
     * 动作IDs【多个','分割】
     *
     * @var
     */
    public $action_ids;

    /**
     * 模块IDs【多个','分割】
     *
     * @var
     */
    public $module_ids;

    /**
     * 角色信息
     *
     * @var array
     */
    protected $role;

    /**
     * 角色权限列表
     *
     * @var array
     */
    protected $rolePermissionList = null;

    /**
     * 删除菜单权限IDs
     *
     * @var array
     */
    protected $deleteMenuIds = [];

    /**
     * 新增菜单权限IDs
     *
     * @var array
     */
    protected $addMenuIds = [];

    /**
     * 删除动作权限IDs
     *
     * @var array
     */
    protected $deleteActionIds = [];

    /**
     * 新增动作权限IDs
     *
     * @var array
     */
    protected $addActionIds = [];

    /**
     * 删除模块权限IDs
     *
     * @var array
     */
    protected $deleteModuleIds = [];

    /**
     * 新增模块权限IDs
     *
     * @var array
     */
    protected $addModuleIds = [];


    public function rules()
    {
        return [
            // 参数验证
            [['project_id', 'name', 'status', 'type'], 'required', 'message' => '{attribute}不能为空', 'on' => ['create']],
            [['project_id', 'id', 'name', 'status'], 'required', 'message' => '{attribute}不能为空', 'on' => ['edit']],
            [['project_id', 'id'], 'required', 'message' => '{attribute}不能为空', 'on' => ['delete']],
            [['project_id', 'id', 'status'], 'required', 'message' => '{attribute}不能为空', 'on' => ['edit_status']],

            [['project_id'], 'checkProjectId', 'skipOnEmpty' => false, 'on' => ['create', 'edit', 'delete', 'edit_status']],
            [['id'], 'checkRole', 'skipOnEmpty' => false, 'on' => ['edit', 'delete', 'edit_status']],
            [['name'], 'checkName', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['desc'], 'checkDesc', 'skipOnEmpty' => true, 'on' => ['create', 'edit']],
            [['status'], 'checkStatus', 'skipOnEmpty' => false, 'on' => ['create', 'edit', 'edit_status']],
            [['type'], 'checkType', 'skipOnEmpty' => false, 'on' => ['create']],
            [['menu_ids'], 'checkMenuIds', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['action_ids'], 'checkActionIds', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['module_ids'], 'checkModuleIds', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
        ];
    }

    public function scenarios()
    {
        $scenarios = parent::scenarios();

        // 新增
        $scenarios['create'] = ['name', 'desc', 'project_id', 'status', 'type', 'menu_ids', 'action_ids', 'module_ids'];

        // 编辑
        $scenarios['edit'] = ['id', 'name', 'desc', 'project_id', 'status', 'menu_ids', 'action_ids', 'module_ids'];

        // 删除
        $scenarios['delete'] = ['id', 'project_id'];

        // 切换部门状态
        $scenarios['edit_status'] = ['id', 'project_id', 'status'];

        return $scenarios;
    }

    /**
     * @return array
     */
    public function attributeLabels()
    {
        return [
            'id' => '角色ID',
            'name' => '角色名称',
            'desc' => '角色说明',
            'project_id' => '项目ID',
            'status' => '状态',
            'type' => '类型',
            'menu_ids' => '菜单IDs',
            'action_ids' => '动作IDs',
            'module_ids' => '模块IDs',
        ];
    }

    /**
     * 检验项目ID
     *
     * @param $attribute
     * @return bool
     */
    public function checkProjectId($attribute)
    {
        if (Yii::$app->user->identity->member->is_super == Member::IS_SUPER_YES) {
            return true;
        }

        $attr = Yii::$app->services->attr->findInfo([
            'member_id' => Yii::$app->user->identity->member_id,
            'project_id' => $this->project_id,
        ]);

        if (!$attr) {
            $this->addError($attribute, '未绑定当前项目，无法操作');
            return true;
        }
    }

    /**
     * 检验角色信息
     *
     * @param $attribute
     * @return bool
     */
    public function checkRole($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        $role = $this->getRole();
        if (!$role) {
            $this->addError($attribute, '参数错误[id_error]');
            return true;
        }

        if ($role->status == Role::STATUS_DELETE) {
            $this->addError($attribute, '角色已删除，无法操作');
            return true;
        }

        if ($role->type != Role::TYPE_NOMAL) {
            if ($this->getScenario() == 'delete'
                || ($this->getScenario() != 'delete' && Yii::$app->user->identity->member->is_super == Member::IS_SUPER_NO)
            ) {
                $this->addError($attribute, '非普通角色，无法操作');
                return true;
            }
        }

        if (($this->getScenario() == 'edit' && $this->status == Role::STATUS_INVALID)
            || $this->getScenario() == 'delete'
            || ($this->getScenario() == 'edit_status' && $this->status == Role::STATUS_INVALID)
        ) {
            $userRole = Yii::$app->services->userRole->findInfo(['role_id' => $this->id]);

            if ($userRole) {
                $this->addError($attribute, "该角色有人员绑定，无法操作");
                return true;
            }
        }
    }

    /**
     * 校验角色名称
     *
     * @param $attribute
     */
    public function checkName($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        $len = mb_strlen($this->name);
        if ($len > 30) {
            $this->addError($attribute, '角色名称过长，最多30个字');
            return true;
        }

        // 是否检验
        $isCheck = true;
        if ($this->getScenario() == 'edit') {
            $role = $this->getRole();
            // 角色参数未改变or系统角色【跳过】
            if ($role->name == $this->name || $role->type == Role::TYPE_INLAY) {
                $isCheck = false;
            }
        }

        if ($isCheck) {
            $roleInfo = Yii::$app->services->role->findInfo([
                'project_id' => $this->project_id,
                'name' => $this->name,
                'status' => [Role::STATUS_INVALID, Role::STATUS_ENABLE],
            ]);

            if ($roleInfo) {
                $this->addError($attribute, "角色【{$this->name}】已存在");
                return true;
            }
        }
    }

    /**
     * 校验角色说明
     *
     * @param $attribute
     */
    public function checkDesc($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        $len = mb_strlen($this->desc);
        if ($len > 150) {
            $this->addError($attribute, '角色说明过长，最多150个字');
            return true;
        }
    }

    /**
     * 校验角色状态
     *
     * @param $attribute
     */
    public function checkStatus($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        if (!in_array($this->status, [Role::STATUS_INVALID, Role::STATUS_ENABLE])) {
            $this->addError($attribute, "参数错误[status_error]");
            return true;
        }
    }

    /**
     * 校验角色类型
     *
     * @param $attribute
     */
    public function checkType($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        if (!in_array($this->type, [Role::TYPE_NOMAL, Role::TYPE_INLAY])) {
            $this->addError($attribute, "角色类型错误");
            return true;
        }

        if ($this->type == Role::TYPE_INLAY) {
            if (Yii::$app->user->identity->member->is_super == Member::IS_SUPER_NO) {
                $this->addError($attribute, "非超管无法新增系统角色");
                return true;
            }
        }
    }

    /**
     * 校验菜单IDs
     *
     * @param $attribute
     */
    public function checkMenuIds($attribute)
    {
        // 菜单列表信息
        $menuIds = $this->menu_ids ? array_unique(explode(',', $this->menu_ids)) : [];
        $menuList = Yii::$app->services->menu->findList(['id' => $menuIds]);
        foreach ($menuList as $row) {
            if ($row['status'] != Menu::STATUS_ENABLE) {
                $this->addError($attribute, "参数错误[menu_ids_error]");
                return true;
            }
        }
        $hasMenuIds = array_column($menuList, 'id');

        // 权限列表
        if ($this->getScenario() == 'create') {
            $roleMenuIds = [];
        } else {
            $rolePermission = $this->getRolePermissionList();
            $roleMenuIds = array_column($rolePermission['menu'], 'permission_id');
        }

        // 删除菜单权限IDs
        $this->deleteMenuIds = array_diff($roleMenuIds, $hasMenuIds);

        // 交集，存在部分
        $hasIds = array_intersect($roleMenuIds, $hasMenuIds);

        // 新增菜单权限IDs
        $this->addMenuIds = array_diff($hasMenuIds, $hasIds);
    }

    /**
     * 校验动作IDs
     *
     * @param $attribute
     */
    public function checkActionIds($attribute)
    {
        // 菜单列表信息
        $actionIds = $this->action_ids ? array_unique(explode(',', $this->action_ids)) : [];
        $actionList = Yii::$app->services->action->findList(['id' => $actionIds]);
        foreach ($actionList as $row) {
            if ($row['status'] != Action::STATUS_ENABLE) {
                $this->addError($attribute, "参数错误[action_ids_error]");
                return true;
            }
        }
        $hasActionIds = array_column($actionList, 'id');

        // 权限列表
        if ($this->getScenario() == 'create') {
            $roleActionIds = [];
        } else {
            $rolePermission = $this->getRolePermissionList();
            $roleActionIds = array_column($rolePermission['action'], 'permission_id');
        }

        // 删除菜单权限IDs
        $this->deleteActionIds = array_diff($roleActionIds, $hasActionIds);

        // 交集，存在部分
        $hasIds = array_intersect($roleActionIds, $hasActionIds);

        // 新增菜单权限IDs
        $this->addActionIds = array_diff($hasActionIds, $hasIds);
    }

    /**
     * 校验模块IDs
     *
     * @param $attribute
     */
    public function checkModuleIds($attribute)
    {
        // 模块列表信息
        $moduleIds = $this->module_ids ? array_unique(explode(',', $this->module_ids)) : [];
        $moduleList = Yii::$app->services->module->findList(['id' => $moduleIds]);
        foreach ($moduleList as $row) {
            if ($row['status'] != Action::STATUS_ENABLE) {
                $this->addError($attribute, "模块状态异常");
                return true;
            }
        }
        $hasModuleIds = array_column($moduleList, 'id');

        // 权限列表
        if ($this->getScenario() == 'create') {
            $roleModuleIds = [];
        } else {
            $rolePermission = $this->getRolePermissionList();
            $roleModuleIds = array_column($rolePermission['module'], 'permission_id');
        }

        // 删除模块权限IDs
        $this->deleteModuleIds = array_diff($roleModuleIds, $hasModuleIds);

        // 交集，存在部分
        $hasIds = array_intersect($roleModuleIds, $hasModuleIds);

        // 新增模块权限IDs
        $this->addModuleIds = array_diff($hasModuleIds, $hasIds);
    }

    /**
     * 获取角色权限
     *
     * @return array
     */
    public function getRolePermissionList()
    {
        if (is_null($this->rolePermissionList)) {
            $role = $this->getRole();

            $rolePermission = Yii::$app->services->rolePermission->findList([
                'project_id' => $role->type == Role::TYPE_NOMAL ? $this->project_id : 0,
                'role_id' => $this->id,
            ]);

            $res = [
                'module' => [],
                'menu' => [],
                'action' => [],
            ];
            foreach ($rolePermission as $row) {
                if ($row['permission_type'] == RolePermission::PERMISSION_TYPE_MENU) {
                    $res['menu'][] = $row;
                } else if ($row['permission_type'] == RolePermission::PERMISSION_TYPE_ACTION){
                    $res['action'][] = $row;
                } else {
                    $res['module'][] = $row;
                }
            }

            $this->rolePermissionList = $res;
        }

        return $this->rolePermissionList;
    }

    /**
     * 获取删除菜单权限IDs
     *
     * @return array
     */
    public function getDeleteMenuIds()
    {
        return $this->deleteMenuIds;
    }

    /**
     * 获取新增菜单权限IDs
     *
     * @return array
     */
    public function getAddMenuIds()
    {
        return $this->addMenuIds;
    }

    /**
     * 获取删除动作权限IDs
     *
     * @return array
     */
    public function getDeleteActionIds()
    {
        return $this->deleteActionIds;
    }

    /**
     * 获取新增动作权限IDs
     *
     * @return array
     */
    public function getAddActionIds()
    {
        return $this->addActionIds;
    }

    /**
     * 获取删除模块权限IDs
     *
     * @return array
     */
    public function getDeleteModuleIds()
    {
        return $this->deleteModuleIds;
    }

    /**
     * 获取新增模块权限IDs
     *
     * @return array
     */
    public function getAddModuleIds()
    {
        return $this->addModuleIds;
    }

    /**
     * 获取角色信息
     *
     * @return array|Role|null
     */
    public function getRole()
    {
        if (empty($this->role)) {
            $this->role = Yii::$app->services->role->findById($this->id);
        }

        return $this->role;
    }
}
